/*---------------------------------------------------------------
 * Confidential and Proprietary
 * Copyright 2006 CMO & Hewlett-Packard Development Company, L.P.
 * All Rights Reserved
 * 
 * Project Name    : SPF
 * Sub Project Name: SPF
 *
 * File Name       : MailUtil.java
 *
 * Modification Log:
 *   Date          Ver.#      By            Description
 *   Nov 8, 2006       1.0       zhangzhm        Created
 *   Nov 22, 2006      1.1       zhangzhm        Add new thread way
 *---------------------------------------------------------------
 */
package com.erdos.common.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;

import javax.activation.DataHandler;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.EmailValidator;

import com.erdos.common.exception.ServiceException;

/**
 * <p>MailUtil is for Email Sending/Receiving</p>
 * @version     1.0     <br/>
 * @author      zhangzhm    
 */
public class MailUtil {
    private static final Log logger = LogFactory.getLog(MailUtil.class);
    private static final EmailValidator emailValidator = EmailValidator.getInstance();//.isValid(value)
	
    public static boolean validateEmail(String email){
		boolean result = false;
		if(email!=null && email.length()>0 && emailValidator.isValid(email)){
			result = true;
		}
		return result;
	}
    		
    public static String retrieveFormat(String formatFileName){
        StringBuffer sb = new StringBuffer("");
        InputStream formatStream = null;
        try{
            formatStream = MailUtil.class.getClassLoader()
                .getResourceAsStream(formatFileName);
            if (formatStream == null) return "";
            InputStreamReader reader = new InputStreamReader(formatStream);
            char[] buf = new char[1024];
            int j = 0;
            while ((j = reader.read(buf)) != -1) {
                sb.append(buf, 0, j);
            }
        }catch(IOException ioe){
            logger.error(MsgFormat.format(AppConstants.COMMON,
                    "Error on Reading email format", UserUtil.getUserID()));

        }finally{
            if(formatStream!=null){
                try{
                    formatStream.close();
                }catch(IOException ioe){}
            }
        }
        return sb.toString();
    }
            
    
    /**
     * Send Email to addresses, with attachment in any format.
     * Example of Excel attachment:
          * ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
          * ExcelWriter.write(formatStream, new BufferedOutputStream(os), sheetNames,
          *         sheets, regions, true, -1);
          * if (formatStream != null) {
          *     formatStream.close();
          * }
          * MailUtil.sendEmail("zhangminjin@hotmail.com,min-jin.zhang@sina.com", "Test-Subject", "Test-Content", 
          *          new BufferedInputStream(new ByteArrayInputStream(os.toByteArray())), 
          *          "application/vnd.ms-excel; charset=UTF-8",
          *          "attachment.xls");
     * @param msg
     * @param addresses, comma separated address strings
     * @param subject
     * @param content
     * @param attachment
     * @param attachMimeType
     * @param attachmentname
     */
    public static void sendEmail(String addresses, String subject, String content,
            InputStream  attachment, String attachContentType, String attachmentname){
        Thread mailthread = new MailUtil().new MailThread(""+UserUtil.getUserID(),addresses,null, subject, content, attachment, attachContentType, attachmentname);
        mailthread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            //e.printStackTrace();
        }
    }
    
    /**
     * 
     * @param addresses, comma separated address strings
     * @param cc , comma separated address strings
     * @param subject
     * @param content
     * @param attachment
     * @param attachContentType
     * @param attachmentname
     */
    public static void sendEmail(String addresses, String cc, String subject, String content,
            InputStream  attachment, String attachContentType, String attachmentname){
        Thread mailthread = new MailUtil().new MailThread(""+UserUtil.getUserID(),addresses,cc, subject, content, attachment, attachContentType, attachmentname);
        mailthread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            //e.printStackTrace();
        }
    }
    /**
     * This class is a private class for internal used. For start another thread to run send email in background
     */
    private class MailThread extends Thread{
        String userName;
        String addresses;
        String cc;
        String subject;
        String content;
        InputStream  attachment;
        String attachContentType;
        String attachmentname;
        public MailThread(String userName,String addresses,String cc, String subject, String content,
                InputStream  attachment, String attachContentType, String attachmentname){
            super();
            this.userName = userName;
            this.addresses=addresses;
            this.cc=cc;
            this.subject=subject;
            this.content=content;
            this.attachment=attachment;
            this.attachContentType=attachContentType;
            this.attachmentname=attachmentname;
        }
        
        public void run(){
            logger.info(MsgFormat.format(AppConstants.COMMON,
                    "Begin sending Email", userName));
            //get JNDI mail session
            Transport transport = null;
            try{
            	//TODO
//                Session session = ServiceLocator.getService().getMailSession(SystemParams.MAIL_SESSION);
            	Session session = null;
            	MimeMessage msg = new MimeMessage(session);
                msg.setSubject(subject);
                msg.setSentDate(new Date());
                msg.setContentLanguage(new String[]{SystemParams.MAIL_ENCODING==null?"UTF-8":SystemParams.MAIL_ENCODING});
                MimeBodyPart mimebodypart = new MimeBodyPart();
                mimebodypart.setDataHandler(
                        new DataHandler(
                                new ByteArrayDataSource(
                                        content==null?"":content, 
                                        SystemParams.MAIL_CONTENTTYPE==null?"text/html; charset=UTF-8":SystemParams.MAIL_CONTENTTYPE,
                                        SystemParams.MAIL_ENCODING==null?"UTF-8":SystemParams.MAIL_ENCODING
                                        )
                                )
                        );
                mimebodypart.setContentLanguage(new String[]{SystemParams.MAIL_ENCODING==null?"UTF-8":SystemParams.MAIL_ENCODING});

                // attach message BODY
                MimeMultipart mimemultipart = new MimeMultipart();
                mimemultipart.addBodyPart(mimebodypart);

                // attach FILE
                if(attachment!=null){
                    mimebodypart = new MimeBodyPart();
                    mimebodypart.setDataHandler(
                            new DataHandler(
                                    new ByteArrayDataSource(attachment, attachContentType)
                                    )
                            );
                    mimebodypart.setFileName(attachmentname); 
                    mimemultipart.addBodyPart(mimebodypart);
                }
                //set message body
                msg.setContent(mimemultipart);

                //Sending Email
                transport = session.getTransport(SystemParams.MAIL_TRANSPORT);
                logger.debug(MsgFormat.format(AppConstants.COMMON,
                        "Connectting to Mail Server...", userName));

                transport.connect();
                logger.debug(MsgFormat.format(AppConstants.COMMON,
                        "Connected.", userName));
                if(addresses!=null && addresses.length()>0){
                    logger.debug(MsgFormat.format(AppConstants.COMMON,
                            "Sending to ", addresses));
                    logger.debug(MsgFormat.format(AppConstants.COMMON,
                            "Sending in Progress....", userName));
                    msg.setRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(addresses,false));
                    if (cc!=null && cc.length()>0) {
                    	msg.setRecipients(MimeMessage.RecipientType.CC, InternetAddress.parse(cc,false));
                    }
                    transport.sendMessage(msg,InternetAddress.parse(addresses,false));
                    logger.debug(MsgFormat.format(AppConstants.COMMON,
                            "Sent out finish.", userName));
                }
                transport.close();
            }catch(NoSuchProviderException nspe){
                logger.error(MsgFormat.format(AppConstants.LOG_PREFIX_MAIL_ERROR,
                        "Error on sending Email", userName));
                if(transport!=null && transport.isConnected()){
                    try{
                        transport.close();
                    }catch(MessagingException me){}
                }
                throw new ServiceException(nspe);
            }catch(MessagingException me){
                logger.error(MsgFormat.format(AppConstants.LOG_PREFIX_MAIL_ERROR,
                        "Error on sending Email", userName));
                if(transport!=null && transport.isConnected()){
                    try{
                        transport.close();
                    }catch(MessagingException me1){}
                }
                throw new ServiceException(me);
            }finally{
                if(transport!=null && transport.isConnected()){
                    try{
                        transport.close();
                    }catch(MessagingException me){}
                }
            }
            logger.info(MsgFormat.format(AppConstants.COMMON,
                    "End sending Email", userName));
        }
    }
}
